package ferp.core.mode;

import ferp.core.ai.strategy.Guess;
import ferp.core.calc.Calculator;
import ferp.core.game.Game;
import ferp.core.game.Input;
import ferp.core.game.Settings;
import ferp.core.game.Trick;
import ferp.core.log.Log;
import ferp.core.player.Hand;
import ferp.core.player.Player;

/**
 * User: olegs
 * Date: 19/05/11 15:11
 */
public class Tricking extends TrickingBase
{
  @Override
  public Player mover(Game g, Settings settings, int current)
  {
    return g.isOpen() && current != g.player.declarer ? g.opponent() : super.mover(g, settings, current);
  }

  @Override
  public void score(Game g, Settings settings)
  {
    Calculator.get(settings.gameFlavor).tricking(g, settings);

    super.score(g, settings);
  }

  @Override
  protected int options(Game.Listener listener, Game g, Settings settings, Input input) throws Game.Error
  {
    if (g.type == Game.Type.UNKNOWN)
    {
      if (g.player.current == g.player.declarer)
        return super.options(listener, g, settings, input);

      return g.opponent().setStandInputOptions(g.options);
    }

    return super.options(listener, g, settings, input);
  }

  @Override
  protected Act act(Game.Listener listener, Game g, Settings settings, Input input) throws Game.Error
  {
    if (g.rounds == 0 && g.player.current != g.player.declarer && g.type == Game.Type.UNKNOWN)
    {
      // set game's type according to an opponent decision
      g.opponent().setGameType(g, input);

      if (g.isOpen())
      {
        // open players' hands
        g.getOpponentHand().open = true;
        g.getPasserHand().open = true;

        listener.onOpenGameType(g, settings, g.opponent(), g.passer());
      }
      else
      {
        Log.debug(Log.TAG, "game type is standing, resetting resolver");

        int h[] = new int[Game.PLAYERS];

        for (int i = 0; i < h.length; ++i)
          h[i] = g.getHand(i).current;

        if (g.trick.current != 0)
          h[Game.previous(g.player.current)] |= Trick.card(g.trick.current, 0).hash;

        listener.onStandingGameType(g, h[0], h[1], h[2], g.trick.current);
      }

      return Act.STAY;
    }

    return super.act(listener, g, settings, input);
  }

  @Override
  protected int guessHumanHand(Game g)
  {
    Player p = g.human();
    int drop = g.getDropHash(0) | g.getDropHash(1);

    return Guess.declarerTrickingHand(Hand.add(g.getHand(p.id()).current, drop), p.isStarting(g), g.sets);
  }
}
